From 6f5aa487ed45f88f0fd0fc8bcd0d4af8d2d67888 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 17 Sep 2014 23:24:22 +0200 Subject: Voronoi biomegen: Added JitterSize and OddRowOffset. --- src/Generating/BioGen.cpp | 148 ++++++++++++++++++++++++---------------------- src/VoronoiMap.cpp | 91 +++++++++++++++++++++++----- src/VoronoiMap.h | 13 +++- 3 files changed, 164 insertions(+), 88 deletions(-) diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index 60ad4e3eb..217ca8f80 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -12,72 +12,6 @@ -//////////////////////////////////////////////////////////////////////////////// -// cBiomeGen: - -cBiomeGen * cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault) -{ - AString BiomeGenName = a_IniFile.GetValueSet("Generator", "BiomeGen", ""); - if (BiomeGenName.empty()) - { - LOGWARN("[Generator] BiomeGen value not set in world.ini, using \"MultiStepMap\"."); - BiomeGenName = "MultiStepMap"; - } - - cBiomeGen * res = NULL; - a_CacheOffByDefault = false; - if (NoCaseCompare(BiomeGenName, "constant") == 0) - { - res = new cBioGenConstant; - a_CacheOffByDefault = true; // we're generating faster than a cache would retrieve data :) - } - else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0) - { - res = new cBioGenCheckerboard; - a_CacheOffByDefault = true; // we're (probably) generating faster than a cache would retrieve data - } - else if (NoCaseCompare(BiomeGenName, "voronoi") == 0) - { - res = new cBioGenVoronoi(a_Seed); - } - else if (NoCaseCompare(BiomeGenName, "distortedvoronoi") == 0) - { - res = new cBioGenDistortedVoronoi(a_Seed); - } - else if (NoCaseCompare(BiomeGenName, "twolevel") == 0) - { - res = new cBioGenTwoLevel(a_Seed); - } - else - { - if (NoCaseCompare(BiomeGenName, "multistepmap") != 0) - { - LOGWARNING("Unknown BiomeGen \"%s\", using \"MultiStepMap\" instead.", BiomeGenName.c_str()); - } - res = new cBioGenMultiStepMap(a_Seed); - - /* - // Performance-testing: - LOGINFO("Measuring performance of cBioGenMultiStepMap..."); - clock_t BeginTick = clock(); - for (int x = 0; x < 5000; x++) - { - cChunkDef::BiomeMap Biomes; - res->GenBiomes(x * 5, x * 5, Biomes); - } - clock_t Duration = clock() - BeginTick; - LOGINFO("cBioGenMultiStepMap for 5000 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); - //*/ - } - res->InitializeBiomeGen(a_IniFile); - - return res; -} - - - - - //////////////////////////////////////////////////////////////////////////////// // cBioGenConstant: @@ -402,8 +336,13 @@ void cBioGenVoronoi::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & void cBioGenVoronoi::InitializeBiomeGen(cIniFile & a_IniFile) { super::InitializeBiomeGen(a_IniFile); - m_Voronoi.SetCellSize(a_IniFile.GetValueSetI("Generator", "VoronoiCellSize", 64)); - InitializeBiomes (a_IniFile.GetValueSet ("Generator", "VoronoiBiomes", "")); + int CellSize = a_IniFile.GetValueSetI("Generator", "VoronoiCellSize", 128); + int JitterSize = a_IniFile.GetValueSetI("Generator", "VoronoiJitterSize", CellSize); + int OddRowOffset = a_IniFile.GetValueSetI("Generator", "VoronoiOddRowOffset", 0); + m_Voronoi.SetCellSize(CellSize); + m_Voronoi.SetJitterSize(JitterSize); + m_Voronoi.SetOddRowOffset(OddRowOffset); + InitializeBiomes(a_IniFile.GetValueSet ("Generator", "VoronoiBiomes", "")); } @@ -846,9 +785,10 @@ void cBioGenTwoLevel::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap { for (int x = 0; x < cChunkDef::Width; x++) { - int MinDist1, MinDist2; - int BiomeGroup = m_VoronoiLarge.GetValueAt(DistortX[x][z], DistortZ[x][z], MinDist1, MinDist2) / 7; - int BiomeIdx = m_VoronoiSmall.GetValueAt(DistortX[x][z], DistortZ[x][z], MinDist1, MinDist2) / 11; + int SeedX, SeedZ, MinDist2; + int BiomeGroup = m_VoronoiLarge.GetValueAt(DistortX[x][z], DistortZ[x][z], SeedX, SeedZ, MinDist2) / 7; + int BiomeIdx = m_VoronoiSmall.GetValueAt(DistortX[x][z], DistortZ[x][z], SeedX, SeedZ, MinDist2) / 11; + int MinDist1 = (DistortX[x][z] - SeedX) * (DistortX[x][z] - SeedX) + (DistortZ[x][z] - SeedZ) * (DistortZ[x][z] - SeedZ); cChunkDef::SetBiome(a_BiomeMap, x, z, SelectBiome(BiomeGroup, BiomeIdx, (MinDist1 < MinDist2 / 4) ? 0 : 1)); } } @@ -987,3 +927,69 @@ void cBioGenTwoLevel::InitializeBiomeGen(cIniFile & a_IniFile) + +//////////////////////////////////////////////////////////////////////////////// +// cBiomeGen: + +cBiomeGen * cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault) +{ + AString BiomeGenName = a_IniFile.GetValueSet("Generator", "BiomeGen", ""); + if (BiomeGenName.empty()) + { + LOGWARN("[Generator] BiomeGen value not set in world.ini, using \"MultiStepMap\"."); + BiomeGenName = "MultiStepMap"; + } + + cBiomeGen * res = NULL; + a_CacheOffByDefault = false; + if (NoCaseCompare(BiomeGenName, "constant") == 0) + { + res = new cBioGenConstant; + a_CacheOffByDefault = true; // we're generating faster than a cache would retrieve data :) + } + else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0) + { + res = new cBioGenCheckerboard; + a_CacheOffByDefault = true; // we're (probably) generating faster than a cache would retrieve data + } + else if (NoCaseCompare(BiomeGenName, "voronoi") == 0) + { + res = new cBioGenVoronoi(a_Seed); + } + else if (NoCaseCompare(BiomeGenName, "distortedvoronoi") == 0) + { + res = new cBioGenDistortedVoronoi(a_Seed); + } + else if (NoCaseCompare(BiomeGenName, "twolevel") == 0) + { + res = new cBioGenTwoLevel(a_Seed); + } + else + { + if (NoCaseCompare(BiomeGenName, "multistepmap") != 0) + { + LOGWARNING("Unknown BiomeGen \"%s\", using \"MultiStepMap\" instead.", BiomeGenName.c_str()); + } + res = new cBioGenMultiStepMap(a_Seed); + + /* + // Performance-testing: + LOGINFO("Measuring performance of cBioGenMultiStepMap..."); + clock_t BeginTick = clock(); + for (int x = 0; x < 5000; x++) + { + cChunkDef::BiomeMap Biomes; + res->GenBiomes(x * 5, x * 5, Biomes); + } + clock_t Duration = clock() - BeginTick; + LOGINFO("cBioGenMultiStepMap for 5000 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); + //*/ + } + res->InitializeBiomeGen(a_IniFile); + + return res; +} + + + + diff --git a/src/VoronoiMap.cpp b/src/VoronoiMap.cpp index 68147ebfc..5ad634fe4 100644 --- a/src/VoronoiMap.cpp +++ b/src/VoronoiMap.cpp @@ -59,8 +59,8 @@ void cVoronoiMap::SetOddRowOffset(int a_OddRowOffset) int cVoronoiMap::GetValueAt(int a_X, int a_Y) { - int MinDist1, MinDist2; - return GetValueAt(a_X, a_Y, MinDist1, MinDist2); + int SeedX, SeedY, MinDist2; + return GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2); } @@ -69,41 +69,47 @@ int cVoronoiMap::GetValueAt(int a_X, int a_Y) int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist) { - int MinDist2; - return GetValueAt(a_X, a_Y, a_MinDist, MinDist2); + int SeedX, SeedY, MinDist2; + int res = GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2); + a_MinDist = (a_X - SeedX) * (a_X - SeedX) + (a_Y - SeedY) * (a_Y - SeedY); + return res; } -int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist1, int & a_MinDist2) +int cVoronoiMap::GetValueAt( + int a_X, int a_Y, // Coords to query + int & a_NearestSeedX, int & a_NearestSeedY, // Coords of the closest cell + int & a_MinDist2 // Distance to the second closest cell +) { - // Note that due to historical reasons, the algorithm uses XZ coords, while the input uses XY coords. - // This is because the algorithm was first implemented directly in the biome generators which use MC coords. - int CellX = a_X / m_CellSize; - int CellZ = a_Y / m_CellSize; + int CellY = a_Y / m_CellSize; - UpdateCell(CellX, CellZ); + UpdateCell(CellX, CellY); // Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell + int NearestSeedX = 0, NearestSeedY = 0; int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this int MinDist2 = MinDist; int res = 0; // Will be overriden for (int x = 0; x < 5; x++) { - for (int z = 0; z < 5; z++) + for (int y = 0; y < 5; y++) { - int SeedX = m_SeedX[x][z]; - int SeedZ = m_SeedZ[x][z]; + int SeedX = m_SeedX[x][y]; + int SeedY = m_SeedZ[x][y]; - int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedZ - a_Y) * (SeedZ - a_Y); + int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y); if (Dist < MinDist) { + NearestSeedX = SeedX; + NearestSeedY = SeedY; MinDist2 = MinDist; MinDist = Dist; - res = m_Noise3.IntNoise2DInt(x + CellX - 2, z + CellZ - 2); + res = m_Noise3.IntNoise2DInt(x + CellX - 2, y + CellY - 2); } else if (Dist < MinDist2) { @@ -112,7 +118,8 @@ int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist1, int & a_MinDist2 } // for z } // for x - a_MinDist1 = MinDist; + a_NearestSeedX = NearestSeedX; + a_NearestSeedY = NearestSeedY; a_MinDist2 = MinDist2; return res; } @@ -121,6 +128,58 @@ int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist1, int & a_MinDist2 +void cVoronoiMap::FindNearestSeeds( + int a_X, int a_Y, + int & a_NearestSeedX, int & a_NearestSeedY, + int & a_SecondNearestSeedX, int & a_SecondNearestSeedY +) +{ + int CellX = a_X / m_CellSize; + int CellY = a_Y / m_CellSize; + + UpdateCell(CellX, CellY); + + // Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell + int NearestSeedX = 0, NearestSeedY = 0; + int SecondNearestSeedX = 0, SecondNearestSeedY = 0; + int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this + int MinDist2 = MinDist; + for (int x = 0; x < 5; x++) + { + for (int y = 0; y < 5; y++) + { + int SeedX = m_SeedX[x][y]; + int SeedY = m_SeedZ[x][y]; + + int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y); + if (Dist < MinDist) + { + SecondNearestSeedX = NearestSeedX; + SecondNearestSeedY = NearestSeedY; + MinDist2 = MinDist; + NearestSeedX = SeedX; + NearestSeedY = SeedY; + MinDist = Dist; + } + else if (Dist < MinDist2) + { + SecondNearestSeedX = SeedX; + SecondNearestSeedY = SeedY; + MinDist2 = Dist; + } + } // for z + } // for x + + a_NearestSeedX = NearestSeedX; + a_NearestSeedY = NearestSeedY; + a_SecondNearestSeedX = SecondNearestSeedX; + a_SecondNearestSeedY = SecondNearestSeedY; +} + + + + + void cVoronoiMap::UpdateCell(int a_CellX, int a_CellZ) { // If the specified cell is currently cached, bail out: diff --git a/src/VoronoiMap.h b/src/VoronoiMap.h index 49f6c1da1..dfb11e9ce 100644 --- a/src/VoronoiMap.h +++ b/src/VoronoiMap.h @@ -40,7 +40,18 @@ public: /** Returns the value in the cell into which the specified point lies, and the distances to the 2 nearest Voronoi seeds. Uses a cache. */ - int GetValueAt(int a_X, int a_Y, int & a_MinDistance1, int & a_MinDistance2); + int GetValueAt( + int a_X, int a_Y, // Coords to query + int & a_NearestSeedX, int & a_NearestSeedY, // Coords of the closest cell's seed + int & a_MinDist2 // Distance to the second closest cell's seed + ); + + /** Finds the nearest and second nearest seeds, returns their coords. */ + void FindNearestSeeds( + int a_X, int a_Y, + int & a_NearestSeedX, int & a_NearestSeedY, + int & a_SecondNearestSeedX, int & a_SecondNearestSeedY + ); protected: /// The noise used for generating Voronoi seeds -- cgit v1.2.3